package com.fengyun;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.support.RootBeanDefinition;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;

/**
 * 模拟循环依赖的过程
 * <p>
 * 将bean添加到singletonObjectS一级缓存中，需要在【给被@Autowired修饰的属性赋值】之前，
 * 如果在属性赋值之后，将bean添加到一级缓存中。
 * 方法会出现死循环，一直递归调用getBean()方法，无法将单例bean添加到单例池中，并且根据beanName从单例池中无法获取到bean实例
 * <p>
 * todo  一级缓存singletonObjects：
 * >>>可以解决单线程情况下的，循环依赖问题！
 * >>>但是在多线程的情况下，假如一个线程调用getBean方法，刚把单例bean创建完成，实例化并没有填充属性和初始化，此时的bean还是一个半成品，被缓存到了单例池中
 * >>>刚好另一个线程调用了getBean()方法，从单例池中获取该bean，只是一个半成品bean。
 * <p>  二级缓存
 *
 */
public class Main {

	public static final Map<String, Object> beanDefinitionMap = new HashMap<>(16);

	// 一级缓存
	public static final Map<String, Object> singletonObjects = new HashMap<>(256);

	public static void loadBeanDefinition() {
		RootBeanDefinition rootBeanDefinitionUsera = new RootBeanDefinition(UserA.class);
		RootBeanDefinition rootBeanDefinitionUserb = new RootBeanDefinition(UserB.class);
		beanDefinitionMap.put("userA", rootBeanDefinitionUsera);
		beanDefinitionMap.put("userB", rootBeanDefinitionUserb);
	}


	/**
	 * 实例化
	 *
	 * @param beanName
	 * @return
	 */
	public static Object getBean(String beanName) {
		try {

			// 从单例池中直接获取bean,获取不到在创建bean
			Object singleton = getSingleton(beanName);
			if (singleton != null) {
				return singleton;
			}

			// 实例化
			RootBeanDefinition rootBeanDefinition = (RootBeanDefinition) beanDefinitionMap.get(beanName);
			Class<?> beanClass = rootBeanDefinition.getBeanClass();

			Object instance = beanClass.getDeclaredConstructors()[0].newInstance();


			/*
			 * 添加到一级缓存中
			 */
			singletonObjects.put(beanName, instance);


			// 给被@Autowired修饰的属性赋值
			Field[] declaredFields = beanClass.getDeclaredFields();
			for (Field declaredField : declaredFields) {
				declaredField.setAccessible(true);
				Autowired autowired = declaredField.getDeclaredAnnotation(Autowired.class);
				if (autowired != null) {
					String name = declaredField.getName();

					// todo 递归操作
					Object bean = getBean(name);


					// 给被@Autowired修饰的属性赋值
					declaredField.set(instance, bean);
				}
			}

			/*
			 * 填充属性
			 */


			/*
			 * 初始化
			 */

			/*
			 * 添加到一级缓存中
			 */
			// singletonObjects.put(beanName, instance);

			return instance;

		} catch (Exception e) {
			e.printStackTrace();
			System.out.println(e.getMessage());
		}

		return null;
	}

	/**
	 * 从单例池中获取bean
	 *
	 * @param beanName
	 * @return
	 */
	public static Object getSingleton(String beanName) {
		if (singletonObjects.containsKey(beanName)) {
			return singletonObjects.get(beanName);
		}
		return null;
	}


	public static void main(String[] args) {
		loadBeanDefinition();

		for (String key : beanDefinitionMap.keySet()) {
			Object bean = getBean(key);
		}
	}
}
